package io.esirong.base;

import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;

import com.orhanobut.logger.Logger;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentTransaction;

import butterknife.ButterKnife;
import butterknife.Unbinder;
import io.esirong.bus.Event;
import io.esirong.util.BusUtils;
import io.esirong.util.ToastUtils;

/**
 * 基本的Activity，继承于Android平台FragmentActivity；
 * Base {@link FragmentActivity} class for every Activity in this
 * application.
 * <P><BR>
 * TODO 完成管理页面要素：StatusBar，ToolBar, ContentView, EmptyView, Dialog, Toast, progress, SnackBar(上/下端）
 * TODO 也可通过其工具类实施
 *
 * @author 黄嵘才
 * @date 2017/7/5
 */
public abstract class BaseActivity extends FragmentActivity {

    /*
     *尽量保持原来的调用方式，不添加抽象方法。使用开关/配置方式来选择需要的功能
     */
    /**
     * 日志标签，其值是实例类的类名称
     */
    private final String TAG = "BaseActivity";
    /**
     * 约定的默认-key。Activity之间的数据对象传递时设置使用
     */
    public static final String RESULT_EXTRA_DATA = "activity:result:data";

    public static final int REQUEST_PERMISSIONS = 3001;
    /**
     * 待请求的应用需要的权限
     */
    protected String[] mPermissions;

    private Unbinder unbinder;
    /**
     * Toolbar界面的头部工具条
     */
    protected Toolbar mToolbar;

    //初始化
    {
        mPermissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setFullScreen();
        setupToolbar();
        registerBus();
    }
    /**
     * 初始界面UI
     */
    protected abstract void initView(View view);

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unBindButterKnife();
        unregisterBus();
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        onPreparedWindow();
        initView(getWindow().getDecorView());
        setupToolbar();
    }

    @Override
    public void setContentView(@LayoutRes int layoutResId) {
        super.setContentView(layoutResId);
        bindButterKnife();
    }

    @Override
    public void setContentView(View view) {
        super.setContentView(view);
        bindButterKnife();
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        super.setContentView(view, params);
        bindButterKnife();
    }

    private void bindButterKnife() {
        unbinder = ButterKnife.bind(this);
    }

    private void unBindButterKnife() {
        if (unbinder != null) {
            unbinder.unbind();
        }
    }

    private void registerBus() {
        if (regEvent()) {
            BusUtils.register(this);
        }
    }

    private void unregisterBus() {
        if (regEvent()) {
            BusUtils.unregister(this);
        }
    }

    /**
     * 获取UI的Toolbar视窗控件
     *
     * @return Toolbar 可能为null
     */
    public Toolbar getToolbar() {
        return mToolbar;
    }

    protected void setupToolbar() {
        if (mToolbar == null) {
            View view = findViewById(R.id.toolbar);
            if (view instanceof Toolbar) {
                mToolbar = (Toolbar) view;
            }
        }
        if (mToolbar == null) {
            return;
        }
        setDisplayBackEnabled(false);
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });
    }

    //还有另一种，是和页截入就开始的异步检查

    /**
     * 页面已装载完成时回调
     * 你可以在这里作弹窗，业务检查，显示UI等
     * <p>?为什么要在页面装载完成回调来务检查，显示UI等操作呢。
     * <p>这是为了降低资源占用，使得显示更快一些，如你的检查是比较消耗时的，那么页面的显示可能受到影响
     */
    protected void onPreparedWindow() {
        //当页面装载已完成时，作页面的初始业务检
        getWindow().getDecorView().post(new Runnable() {
            @Override
            public void run() {
                attemptRequestPermissionForApp();
                //其他在页面UI后执行的动作。
            }
        });
    }

    public void setDisplayBackEnabled(boolean enabled) {
    }

    /**
     * 设置左侧返回按钮的图标
     */
    public void setToolbarLeftDrawable(int resId) {
        if (mToolbar != null) {
            mToolbar.setNavigationIcon(resId);
        }
    }

    /**
     * 设置左侧返回按钮的图标
     */
    public void setToolbarLeftDrawable(Drawable drawable) {
        if (mToolbar != null) {
            mToolbar.setNavigationIcon(drawable);
        }
    }

    @Override
    protected void onTitleChanged(CharSequence title, int color) {
        super.onTitleChanged(title, color);
    }

    /**
     * Adds a {@link Fragment} to this activity's layout.
     *
     * @param containerViewId The container view to where add the fragment.
     * @param fragment        The fragment to be added.
     */
    protected void addFragment(int containerViewId, Fragment fragment) {
        final FragmentTransaction fragmentTransaction = this.getSupportFragmentManager()
                .beginTransaction();
        fragmentTransaction.add(containerViewId, fragment);
        fragmentTransaction.commit();
    }

    /**
     * 显示fragment
     *
     * @param containerViewId The container view to where add the fragment.
     * @param fragment        The fragment to be added.
     */
    protected void showFragment(int containerViewId, Fragment fragment) {
        FragmentTransaction fragmentTransaction = this.getSupportFragmentManager().beginTransaction();
        if (!fragment.isAdded()) {
            fragmentTransaction.add(containerViewId, fragment);
        }
        fragmentTransaction.show(fragment);
        fragmentTransaction.commitAllowingStateLoss();
    }

    /**
     * activity是不是处于可以正常使用情况
     *
     * @return 可以正常使用
     */
    public boolean activityIsAlive() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            return !(isDestroyed() || isFinishing());
        } else {
            return !isFinishing();
        }
    }

    /*
     *START===
     * 权限管理
     */

    /**
     * 返回需要请求的权限; 子类重写，返回需要的权限。重写以下可以获得申请结果的调用
     * <p>{@link #onPermissionGranted()};申请通过
     * <p>{@link #onPermissionRejected(List)};申请拒绝
     * <p>{@link #onPermissionGrantedFailure()}; 申请失败
     *
     * @return 权限列表
     */
    protected String[] onNeedPermissions() {
        return mPermissions;
    }

    /**
     * 获取申请动态权限通过。子类可以重写以处理实际的逻辑
     */
    protected void onPermissionGranted() {
        // 空
    }

    /**
     * 申请动态权限未通过。子类可以重写以处理实际的逻辑
     */
    protected void onPermissionGrantedFailure() {
        // 空
    }

    /**
     * 获取申请动态权限被完全拒绝的。子类可以重写以处理实际的逻辑
     */
    protected void onPermissionRejected(List<String> needPermissions) {
        // 空
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        handleOnPermissionResult(requestCode, permissions, grantResults);
    }

    /**
     * 尝试申请应用必需要的权限
     */
    private void attemptRequestPermissionForApp() {
        if (onNeedPermissions() == null || onNeedPermissions().length <= 0) {
            return;
        }
        String[] pendPermissions = checkSelfPermission(onNeedPermissions());
        requestPermissions(pendPermissions);
    }

    protected String[] checkSelfPermission(String[] permissions) {
        if (permissions == null || permissions.length <= 0) {
            return permissions;
        }
        // 待申请的权限（含被拒绝的部分）
        List<String> pendPermissions = new ArrayList<>(permissions.length);
        // （含被拒绝的部分）
        List<String> rejectedPermissions = new ArrayList<>(permissions.length);
        for (String per : permissions) {
            //检查需要的权限是不是已被授以
            Boolean granted = checkPermission(per);
            if (null == granted) {
                rejectedPermissions.add(per);
            }
            if (null == granted || !granted) {
                pendPermissions.add(per);
            }
        }
        if (rejectedPermissions.size() > 0) {
            onPermissionRejected(rejectedPermissions);
        }

        if (pendPermissions.size() > 0) {
            String[] array = new String[pendPermissions.size()];
            return pendPermissions.toArray(array);
        }
        return null;
    }

    /**
     * 检查权限
     *
     * @param permission 权限
     * @return true:已获得授权; false:不获得授权; null:完全被拒授权(发起申请被忽略）
     */
    protected Boolean checkPermission(String permission) {
        if (ContextCompat.checkSelfPermission(getApplicationContext(), permission)
                == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
                return false;
            } else {
                return null;
            }
        }
    }

    protected void requestPermissions(String[] permissions) {
        if (permissions == null || permissions.length <= 0) {
            return;
        }
        ActivityCompat.requestPermissions(this,
                permissions,
                REQUEST_PERMISSIONS);
    }


    private void handleOnPermissionResult(int requestCode,
                                          @NonNull String[] permissions,
                                          @NonNull int[] grantResults) {

        Logger.e("permissions:" + Arrays.toString(permissions)
                + " grantResults:" + Arrays.toString(grantResults));
        switch (requestCode) {
            case REQUEST_PERMISSIONS: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    onPermissionGranted();
                } else {
                    onPermissionGrantedFailure();
                }
            }
            default:
                break;
        }
    }

    /*
     * END===
     * 权限管理
     */

    private void setFullScreen() {
        setFullScreen(fullScreen());
    }

    /**
     * Activity全屏显示
     * <P> 整个Activity页全屏显示，没有状态栏StatusBar
     *
     * @param enable true 全屏显示； false不是
     */
    protected final void setFullScreen(boolean enable) {
        WindowManager.LayoutParams lp = getWindow().getAttributes();
        if (enable) {
            lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
            getWindow().setAttributes(lp);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
        } else {
            lp.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getWindow().setAttributes(lp);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
        }
    }

    public void showEmpty() {
    }

    public void showEmpty(@LayoutRes int layoutResId) {
    }

    public void showEmpty(View view) {
    }

    /**
     * 显示Toast ，会根据字数的多少动态调节显示时长
     *
     * @param msg 显示的内容
     */
    public void showToast(String msg) {
        ToastUtils.showToast(this, msg);
    }

    /**
     * 显示对话框
     * 需要获得用户交互才会隐去的消息窗
     *
     * @param msg 显示的内容
     */
    public void showDialog(String msg) {

    }

    /****=====================子类重写，开启/关闭功能===================

     /**
     * 子类接受事件 重写该方法
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventBus(Event<?> event) {
    }

    /**
     * 控制配置子类重写，以确定是不是全屏显示
     */
    protected boolean fullScreen() {
        return false;
    }

    /**
     * 是否需要ActionBar
     * TODO 暂时用此方法 后续优化
     */
    protected boolean isActionBar() {
        return false;
    }

    /**
     * 需要接收事件 重写该方法 并返回true
     */
    protected boolean regEvent() {
        return false;
    }


    public void showLoading() {
        //
    }

    public void dismissLoading() {

    }

    public void onEmpty(Object tag) {

    }

    /**
     * 显示应用的错误信息
     *
     * @param tag      持有对象（即默认this,当对执行对对象，也可以指定）
     * @param errorMsg 错误信息
     */
    public void onError(Object tag, String errorMsg) {
    }

    public void showDialog() {

    }

}
